home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok03.lha / IFFLoad_1.1 / IFFLoad.mod < prev    next >
Text File  |  1993-08-15  |  23KB  |  657 lines

  1. (*---------------------------------------------------------------------------
  2.     :Program.    IFFLoad.mod
  3.     :Author.     Fridtjof Siebert
  4.     :Address.    Nobileweg 67, D-7-Stgt-40
  5.     :Phone.      0711/822509
  6.     :Shortcut.   [fbs]
  7.     :Version.    1.1
  8.     :Date.       20-May-88
  9.     :Copyright.  Shareware or PD, anyway you like. (I like Shareware better)
  10.     :Language.   Modula-II
  11.     :Translator. M2Amiga
  12.     :Imports.    LoadBody.asm [fbs]
  13.     :UpDate.     07-Jun-88: Maschinensprachteil [fbs]
  14.     :Contents.   Schnelle Ladeprozedur für IFF (ILBM)-Bilder.
  15.     :Remark.     Let's wave! The Cure. The Mission. Sisters of Mercy !!!
  16. ---------------------------------------------------------------------------*)
  17. IMPLEMENTATION MODULE IFFLoad;
  18.  
  19. FROM SYSTEM    IMPORT ADR, ADDRESS, SHIFT, BITSET, LONGSET, CAST, INLINE,
  20.                       REG;
  21.  
  22. FROM Exec      IMPORT AllocMem, FreeMem, MemReqs, MemReqSet, UByte,
  23.                       Interrupt, AddIntServer, RemIntServer, NodeType;
  24. FROM Dos       IMPORT FileHandlePtr, Open, Close, Read, oldFile;
  25. FROM Intuition IMPORT NewScreen, ScreenPtr, OpenScreen, CloseScreen,
  26.                       ScreenToBack, ScreenFlags, ScreenFlagSet,
  27.                       customScreen, MoveScreen, WindowPtr, OpenWindow,
  28.                       CloseWindow, IDCMPFlags, IDCMPFlagSet, WindowFlags,
  29.                       WindowFlagSet;
  30. FROM Graphics  IMPORT SetRGB4, RastPortPtr, BitMapPtr, ViewModes,
  31.                       ViewModeSet, BitMap, InitBitMap, AllocRaster,
  32.                       BltClear, FreeRaster, ViewPortPtr;
  33. FROM GfxMacros IMPORT OffDisplay, OnDisplay;
  34. FROM Hardware  IMPORT vertb;
  35.  
  36. FROM Arts      IMPORT TermProcedure, Assert;
  37. FROM Strings   IMPORT Compare, first, last;
  38.  
  39. FROM LoadBody  IMPORT LoadBody;
  40.  
  41. (*---------------------------------------------------------------------------
  42. !                                                                           !
  43. !                        Variables from Definition:                         !
  44. !                                                                           !
  45. -----------------------------------------------------------------------------
  46.  
  47. (*---------------------------  Types:  ------------------------------------*)
  48.  
  49. TYPE
  50.   IFFTitles = (BMHD,CMAP,GRAB,DEST,CAMG,CRNG,BODY,SPRT,CCRT,CMHD,DPPV);
  51.   IFFTitleSet = SET OF IFFTitles;
  52. (* SPRT,CCRT,CMHD,DPPV not implemented !!!                                 *)
  53.  
  54.   ViewTypes = (vt0,Ersy,Lace,LPen,vt4,vt5,vt6,vt7,Gaud,Color,DblPF,HoMod,
  55.                vt12,vt13,vt14,Hires,v16);
  56.   ViewTypeSet = SET OF ViewTypes;
  57. (* which ViewModes are selected *)
  58.  
  59. TYPE
  60.  
  61. (*-------------  The Structure that keeps all the data:  ------------------*)
  62. (* You don't have to understand all variables in this structure! Only some *)
  63. (* are important, like BMHD.width/height or CMAP.red[] etc. The other data *)
  64. (* is used by the Routines that are exported from this module,like DoCycle *)
  65. (* etc.                                                                    *)
  66.  
  67.   IFFInfoTypePtr = POINTER TO IFFInfoType;
  68.   IFFInfoType = RECORD
  69.   (* This contains all Data needed for a Picture *)
  70.  
  71. (*------  Which Data is availble:  ------*)
  72.     IFFTitle: IFFTitleSet;     (* all Sub-Records, whose equally named Flag*)
  73. (* is set here, contain readable data                                      *)
  74.  
  75. (*------  Information on BitMap:  ------*)
  76.     BMHD: RECORD
  77.  
  78.       width,height: INTEGER;   (* the Picture's Size                       *)
  79.       depth: UByte;            (* it's Depth (how many BitPlanes)          *)
  80.       left,top: INTEGER;       (* it's Location                            *)
  81.       masking: UByte;          (* Masking (see Documentation)              *)
  82.       transCol: INTEGER;       (* Transparent Color                        *)
  83.       xAspect,yAspect: UByte;  (* Verzerrung                               *)
  84.       scrnWidth,scrnHeight: INTEGER; (* The Image's Screen's Size          *)
  85.     END;
  86.  
  87. (*------  Information on Colors:  ------*)
  88.     CMAP: RECORD
  89.  
  90.       colorCnt: CARDINAL;      (* Number of Colors used                    *)
  91.       red,green,blue:   ARRAY[0..63] OF UByte;
  92.        (* the Colors (I hope for 6 Bitplanes to be possible anytime)       *)
  93.     END;
  94.  
  95. (*------  Information on HotSpot:  ------*)
  96.     GRAB: RECORD
  97.  
  98.       hotX,hotY: INTEGER;      (* Hot-Spot of this Image (if exists        *)
  99.     END;
  100.  
  101. (*------  Information on Destination-Bitmap:  ------*)
  102.     DEST: RECORD
  103.       depth: UByte;            (* number of Planes                         *)
  104.       planePick: CARDINAL;
  105.       planeOnOff: CARDINAL;    (* set or clear other Planes ?              *)
  106.       planeMask: CARDINAL;     (* planes to be changed                     *)
  107.     END;
  108.  
  109. (*------  Information on any Special ViewMode:  ------*)
  110.     CAMG: RECORD
  111.       viewType: ViewTypeSet;   (* ViewMode                                 *)
  112.     END;
  113.  
  114. (*------  Information on ColorCycling:  ------*)
  115.     CRNG: RECORD
  116.       count: CARDINAL;         (* Number of ColorCyclings                  *)
  117.       data: ARRAY[0..15] OF RECORD
  118.  
  119.         rate: INTEGER;         (* velocity, 800H is 60 per second          *)
  120.         on: BOOLEAN;           (* decide, wether CRNG is active or not     *)
  121.         forward: BOOLEAN;      (* Direction (DPaint)                       *)
  122.         low,high: UByte;       (* lower and upper Color of this Range      *)
  123.       END;
  124.     END;
  125. (*------  Internal Information:  ------*)
  126.     Internal: RECORD
  127.       CycleID: CARDINAL;       (* that's to distinguish different cyclings *)
  128.     END;
  129.   END;
  130.  
  131. (* That's been quite a complex Variable. If you wanna use it, do it this   *)
  132. (* way:                                                                    *)
  133. (* e.g. You wanna know, how Deep your Image is. Ça marche comme ça:        *)
  134. (* MyDepth := IFFInfo.BMHD.depth;                                          *)
  135. (* You can get the speed of the second Colorcycle this way:                *)
  136. (* speed := IFFInfo.CRNG.data[2].rate;                                     *)
  137.  
  138. (*--------------  That's the Variable, that contains all Data  ------------*)
  139. (* this should be imported to your Module to get the Data. Don't forget to *)
  140. (* save the data, e.g. to a variable of the same type. Everytime you load  *)
  141. (* a new IFF-File, the data is scratched !!! (i.e. the new data is written *)
  142. (* into this structure.)                                                   *)
  143.  
  144. VAR
  145.   IFFInfo: IFFInfoType;
  146.  
  147. (*--------------------  The NewScreen-Structure.  -------------------------*)
  148. (* this can be used to open the Screen, if dontopen is specified           *)
  149.  
  150. VAR
  151.   NuScreen: NewScreen;
  152.  
  153. (*--------------------  The NewWindow-Structure.  -------------------------*)
  154. (* this can be used to open the Window later. Don't forget to put Screen-  *)
  155. (* Ptr in NuWindow.screen !!!                                              *)
  156.  
  157. VAR
  158.   NuWindow: NewWindow;
  159.  
  160. *)
  161.  
  162. (*-------------------------------------------------------------------------*)
  163. (*                                                                         *)
  164. (*                     Internal Variables and Types:                       *)
  165. (*                                                                         *)
  166. (*-------------------------------------------------------------------------*)
  167.  
  168. CONST
  169.     MOVEMS = 48E7H; (* that's the 68000-Instruction MOVEM to save Registers*)
  170.     MOVEML = 4CDFH; (* that's MOVEM to load Registers                      *)
  171.  
  172. TYPE
  173.   CyclingInfo = RECORD
  174.     int: Interrupt;   (* The Cycling's Interrupt *)
  175.     VP: ViewPortPtr;  (* The Cycling's ViewPort *)
  176.     count: ARRAY[0..15] OF CARDINAL;   (* counts Cycling-Positions *)
  177.     speedCnt: ARRAY[0..15] OF CARDINAL; (* counts Speed *)
  178.          (* The Cycling-Direction (TRUE=Forwards) *)
  179.   END;
  180.  
  181. VAR
  182.   InH: FileHandlePtr;
  183.   i,j,k: LONGINT;
  184.   length: INTEGER;
  185.   LineLength: LONGINT;         (* Bytes per Image-Line                     *)
  186.   LineWidth: LONGINT;          (* Bytes per Screen-Line                    *)
  187.   BM: BitMapPtr;
  188.   Compression: BOOLEAN;        (* Decide, wether data is compressed or not *)
  189.   MaskPlane: BOOLEAN;          (* Is there a Mask-Plane ??                 *)
  190.   Buffer: ADDRESS;
  191.   TextBuffer: POINTER TO ARRAY[0..63] OF ARRAY[0..3] OF CHAR;
  192.   LONGBuffer: POINTER TO ARRAY[0..63] OF LONGCARD;
  193.   WORDBuffer: POINTER TO ARRAY[0..127] OF INTEGER;
  194.   BYTEBuffer: POINTER TO ARRAY[0..255] OF UByte;
  195.   len: LONGINT;
  196.   BitMaps: ARRAY[0..5] OF ADDRESS;
  197.   Byte,Byte2: UByte;
  198.   Line,Plane: LONGINT;
  199.   Location,Right: POINTER TO UByte;
  200.   RQPos,RQLen: LONGCARD;
  201.   RQBuffer: POINTER TO ARRAY[0..511] OF UByte;
  202.   SpecialView: LONGSET;
  203.   Exit: BOOLEAN;
  204.   NoErr: BOOLEAN;
  205.   CycleInfos: ARRAY[0..31] OF CyclingInfo;
  206.   IntInfo: IFFInfoTypePtr;
  207.   IntNum: CARDINAL;
  208.   IntCount,IntCount2,IntCount3: CARDINAL;
  209.  
  210. (*-----------  Procedure called by machinecode to get Data:  --------------*)
  211.  
  212. PROCEDURE Read512();
  213.  
  214. BEGIN
  215.   len := Read(InH,RQBuffer,512);
  216. END Read512;
  217.  
  218. (*-------------------------------------------------------------------------*)
  219. (*                                                                         *)
  220. (*                          R e a d  I L B M :                             *)
  221. (*                                                                         *)
  222. (*-------------------------------------------------------------------------*)
  223.  
  224. (*
  225. TYPE
  226.   ReadILBMFlags = (front,visible,dontopen,window);
  227.   ReadILBMFlagSet = SET OF ReadILBMFlags;
  228. *)
  229.  
  230. PROCEDURE ReadILBM(name: ARRAY OF CHAR; Flags: ReadILBMFlagSet;
  231.                    VAR Screen: ScreenPtr; VAR Window: WindowPtr): BOOLEAN;
  232. (* ReadILBM() lädt ein IFF-Bild und öffnet das geladene Bild als Screen.   *)
  233. (* Name: The IFF-Filename                                                  *)
  234. (* Flags:                                                                  *)
  235. (*  -front: decides whether Screen is first or last one while loading      *)
  236. (*  -visible: decides if display should be turned off (that's faster)      *)
  237. (*  -dontopen: avoids to open the Screen. The Returned value is NIL. The   *)
  238. (*     BitMap of the loaded Imagery can be found in NuScreen.customBitMap. *)
  239. (*     Don't forget to free the image's Memory if it's no more needed and  *)
  240. (*     the Memory needed for the BitMap-Structure.                         *)
  241. (*  -window: if set, an Window of the same size as the Image is opened.    *)
  242. (*           So, Gadgets etc. can be added to it.                          *)
  243. (* Screen: Pointer to Screen-structure of opened Screen                    *)
  244. (* Window: Pointer to the opened Window or NIL if window isn't set.        *)
  245. (* Result: FALSE if error occured. Then there's no Screen opened.          *)
  246.  
  247. PROCEDURE OpenScrn();
  248. (* this initializes the Screen, Window and Bitmap, if they're needed.      *)
  249. (* Screen and Window are opened.                                           *)
  250.  
  251.   BEGIN
  252.     WITH NuScreen DO
  253.       width := IFFInfo.BMHD.scrnWidth;
  254.       IF width<IFFInfo.BMHD.width THEN
  255.         width := IFFInfo.BMHD.width;
  256.       END;
  257.       height := IFFInfo.BMHD.scrnHeight;
  258.       IF height<IFFInfo.BMHD.height THEN
  259.         height := IFFInfo.BMHD.height;
  260.       END;
  261.       leftEdge := IFFInfo.BMHD.left;
  262.       topEdge := IFFInfo.BMHD.top;
  263.       depth := IFFInfo.BMHD.depth;
  264.       viewModes := ViewModeSet{};
  265.       IF (width>400) AND (depth<5) THEN INCL(viewModes,hires) END;
  266.       IF height>300 THEN INCL(viewModes,lace) END;
  267.       IF Lace  IN IFFInfo.CAMG.viewType THEN INCL(viewModes,lace  ) END;
  268.       IF HoMod IN IFFInfo.CAMG.viewType THEN INCL(viewModes,ham   ) END;
  269.       IF Hires IN IFFInfo.CAMG.viewType THEN INCL(viewModes,hires ) END;
  270.       IF DblPF IN IFFInfo.CAMG.viewType THEN INCL(viewModes,dualpf) END;
  271.       IF (ViewTypeSet{} = (ViewTypeSet{DblPF,HoMod} * IFFInfo.CAMG.viewType))
  272.          AND (depth=6) THEN
  273.         INCL(viewModes,extraHalfbrite);
  274.       END;
  275.       detailPen := 0; blockPen := 0;
  276.       type := customScreen+ScreenFlagSet{screenQuiet};
  277.       font := NIL;
  278.       defaultTitle := NIL;
  279.       gadgets := NIL;
  280.       customBitMap := NIL;
  281.       IF NOT(front IN Flags) THEN topEdge := 600 END;
  282.     END;
  283.     IF dontopen IN Flags THEN
  284.       INCL(NuScreen.type,customBitMap);
  285.       WITH NuScreen DO
  286.         customBitMap := AllocMem(SIZE(BitMap),MemReqSet{public});
  287.         InitBitMap(customBitMap^,depth,width,height);
  288.         i:=0;
  289.         REPEAT
  290.           customBitMap^.planes[i] := AllocRaster(width,height);
  291.           BitMaps[i] := customBitMap^.planes[i];
  292.           IF BitMaps[i]=NIL THEN
  293.             NoErr:=FALSE
  294.           ELSE
  295.             BltClear(BitMaps[i],width DIV 8 * height,0);
  296.           END;
  297.           INC(i);
  298.         UNTIL (i=depth) OR NOT(NoErr);
  299.         IF NOT(NoErr) THEN (* error: give allocated Mem back: *)
  300.           WHILE i>1 DO
  301.             DEC(i);
  302.             FreeRaster(BitMaps[i],width,height);
  303.           END;
  304.         END;
  305.       END;
  306.     ELSE
  307.       Screen := OpenScreen(NuScreen);
  308.       IF Screen=NIL THEN
  309.         NoErr := FALSE;
  310.       ELSE
  311.         IF NOT(front IN Flags) THEN
  312.           ScreenToBack(Screen);
  313.           MoveScreen(Screen,0,-600);
  314.         END;
  315.         BM := Screen^.rastPort.bitMap;
  316.         FOR i:=0 TO NuScreen.depth-1 DO
  317.           BitMaps[i] := BM^.planes[i];
  318.         END;
  319.         WITH IFFInfo.CMAP DO
  320.           FOR i:=0 TO colorCnt-1 DO
  321.             SetRGB4(ADR(Screen^.viewPort),i,red[i],green[i],blue[i]);
  322.           END;
  323.         END;
  324.       END;
  325.     END;
  326.     WITH NuWindow DO
  327.       leftEdge := 0;
  328.       topEdge := 0;
  329.       width := IFFInfo.BMHD.width;
  330.       height := IFFInfo.BMHD.height;
  331.       detailPen := 1;
  332.       blockPen := 0;
  333.       idcmpFlags := IDCMPFlagSet{};
  334.       flags := WindowFlagSet{borderless,noCareRefresh};
  335.       firstGadget := NIL;
  336.       checkMark := NIL;
  337.       title := NIL;
  338.       screen := Screen;
  339.       bitMap := NIL;
  340.       type := customScreen;
  341.     END;
  342.     IF (window IN Flags) AND (Screen#NIL) THEN
  343.       Window := OpenWindow(NuWindow);
  344.       IF Window=NIL THEN
  345.         CloseScreen(Screen);
  346.         Screen := NIL;
  347.         NoErr := FALSE;
  348.       END;
  349.     END;
  350.     IF NOT(visible IN Flags) THEN OffDisplay() END;
  351.   END OpenScrn;
  352.  
  353. PROCEDURE ReadQuick(To: ADDRESS; Count: CARDINAL);
  354.  
  355.   VAR
  356.     ToPtr: POINTER TO ARRAY[0..9999] OF UByte;
  357.     i: CARDINAL;
  358.  
  359.   BEGIN
  360.     ToPtr := To;
  361.     i := 0;
  362.     REPEAT
  363.       IF RQPos=RQLen THEN
  364.         RQLen := Read(InH,RQBuffer,512);
  365.         RQPos := 0;
  366.       END;
  367.       ToPtr^[i] := ORD(RQBuffer^[RQPos]);
  368.       INC(RQPos); INC(i);
  369.     UNTIL i=Count;
  370.   END ReadQuick;
  371.  
  372. BEGIN
  373.   IFFInfo.IFFTitle := IFFTitleSet{};
  374.  
  375.   IF NOT(visible IN Flags) THEN OffDisplay() END;
  376.   NoErr := TRUE; Screen := NIL; Window := NIL;
  377.   RQPos := 0; RQLen := 0;
  378.  
  379.   InH := Open(ADR(name),oldFile);
  380.   IF InH=NIL THEN NoErr := FALSE END;
  381.  
  382.   IF NoErr THEN
  383.  
  384. (*------  File Header:  ------*)
  385.  
  386.     len := Read(InH,Buffer,12);
  387.     IF (len=NIL) OR (Compare(TextBuffer^[0],first,4,"FORM",TRUE)#0) OR
  388.     (Compare(TextBuffer^[2],first,4,"ILBM",TRUE)#0) THEN NoErr := FALSE END;
  389.  
  390.     Exit := FALSE;
  391.  
  392. (*------  Main Loop:  ------*)
  393.  
  394.     WHILE NoErr AND NOT(Exit) DO
  395.       len := Read(InH,Buffer,4);
  396.  
  397.   (*------  BMHD:  ------*)
  398.  
  399.       IF Compare(TextBuffer^[0],first,4,"BMHD",TRUE)=0 THEN
  400.         INCL(IFFInfo.IFFTitle,BMHD);
  401.         len := Read(InH,Buffer,4);
  402.         len := Read(InH,Buffer,LONGBuffer^[0]);
  403.         WITH IFFInfo.BMHD DO
  404.           width     := WORDBuffer^[0];
  405.           height    := WORDBuffer^[1];
  406.           left      := WORDBuffer^[2];
  407.           top       := WORDBuffer^[3];
  408.           depth     := BYTEBuffer^[8];
  409.           masking   := BYTEBuffer^[9];
  410.           MaskPlane := masking=1;
  411.           Compression := BYTEBuffer^[10]=1;
  412.           transCol  := WORDBuffer^[6];
  413.           xAspect   := BYTEBuffer^[14];
  414.           yAspect   := BYTEBuffer^[15];
  415.           scrnWidth := WORDBuffer^[8];
  416.           scrnHeight:= WORDBuffer^[9];
  417.         END;
  418.  
  419.   (*------  CMAP:  ------*)
  420.  
  421.       ELSIF Compare(TextBuffer^[0],first,4,"CMAP",TRUE)=0 THEN
  422.         INCL(IFFInfo.IFFTitle,CMAP);
  423.         len := Read(InH,Buffer,4);
  424.         i := LONGBuffer^[0];
  425.         len := Read(InH,Buffer,i);
  426.         WITH IFFInfo.CMAP DO
  427.           colorCnt := i DIV 3;
  428.           j := 0;
  429.           FOR k:=0 TO colorCnt DO
  430.             red  [k] := SHIFT(BYTEBuffer^[j  ],-4);
  431.             green[k] := SHIFT(BYTEBuffer^[j+1],-4);
  432.             blue [k] := SHIFT(BYTEBuffer^[j+2],-4);
  433.             INC(j,3);
  434.           END;
  435.           INC(colorCnt);
  436.         END;
  437.  
  438.   (*------  CAMG:  ------*)
  439.  
  440.       ELSIF Compare(TextBuffer^[0],first,4,"CAMG",TRUE)=0 THEN
  441.         INCL(IFFInfo.IFFTitle,CAMG);
  442.         len := Read(InH,Buffer,8);
  443.         IFFInfo.CAMG.viewType := CAST(ViewTypeSet,LONGBuffer^[1]);
  444.  
  445.   (*------  GRAB:  ------*)
  446.  
  447.       ELSIF Compare(TextBuffer^[0],first,4,"GRAB",TRUE)=0 THEN
  448.         INCL(IFFInfo.IFFTitle,GRAB);
  449.         len := Read(InH,Buffer,8);
  450.         IFFInfo.GRAB.hotX := WORDBuffer^[2];
  451.         IFFInfo.GRAB.hotY := WORDBuffer^[3];
  452.  
  453.   (*------  DEST:  ------*)
  454.  
  455.       ELSIF Compare(TextBuffer^[0],first,4,"DEST",TRUE)=0 THEN
  456.         INCL(IFFInfo.IFFTitle,DEST);
  457.         len := Read(InH,Buffer,12);
  458.         WITH IFFInfo.DEST DO
  459.           depth      := BYTEBuffer^[4];
  460.           planePick  := WORDBuffer^[3];
  461.           planeOnOff := WORDBuffer^[4];
  462.           planeMask  := WORDBuffer^[5];
  463.         END;
  464.  
  465.   (*------  CRNG:  ------*)
  466.  
  467.       ELSIF Compare(TextBuffer^[0],first,4,"CRNG",TRUE)=0 THEN
  468.         IF NOT(CRNG IN IFFInfo.IFFTitle) THEN
  469.           IFFInfo.CRNG.count := 0;
  470.         END;
  471.         INCL(IFFInfo.IFFTitle,CRNG);
  472.         len := Read(InH,Buffer,12);
  473.         WITH IFFInfo.CRNG.data[IFFInfo.CRNG.count] DO
  474.           rate := WORDBuffer^[3];
  475.           on   := 0 IN CAST(BITSET,WORDBuffer^[4]);
  476.           forward := NOT(1 IN CAST(BITSET,WORDBuffer^[4]));
  477.           low  := BYTEBuffer^[10];
  478.           high := BYTEBuffer^[11];
  479. (* this line is only to identify illegal data, that some IFF-Files contain:*)
  480.           on := on AND (low<IFFInfo.CMAP.colorCnt)
  481.                 AND (high<IFFInfo.CMAP.colorCnt);
  482.         END;
  483.         INC(IFFInfo.CRNG.count);
  484.  
  485.   (*------  BODY:  ------*)
  486.  
  487.       ELSIF Compare(TextBuffer^[0],first,4,"BODY",TRUE)=0 THEN
  488.         OpenScrn();
  489.         IF NoErr THEN
  490.           len := Read(InH,Buffer,4);
  491.           LineLength := SHIFT(SHIFT(CAST(INTEGER,CAST(BITSET,
  492.                         IFFInfo.BMHD.width+15) * {4..15}),-4),1);
  493.           LineWidth  := SHIFT(NuScreen.width,-3);
  494.           IF Compression THEN
  495.           (*------  let's load the BitMap's Data:  ------*)
  496.             LoadBody(Read512, RQBuffer, ADR(BitMaps[0]), LineLength,
  497.                      LineWidth, IFFInfo.BMHD.height, NuScreen.depth,
  498.                      MaskPlane); (* this does all the work very quickly *)
  499.           ELSE   (* not compressed *)
  500.           (*------  to load uncompressed Images is less time-critical: *)
  501.             FOR Line := 0 TO IFFInfo.BMHD.height-1 DO
  502.               FOR Plane := 0 TO NuScreen.depth-1 DO
  503.                 ReadQuick(BitMaps[Plane]+ LineWidth*Line,LineLength);
  504.               END;
  505.               IF MaskPlane THEN
  506.                 ReadQuick(Buffer,LineLength);
  507.               END;
  508.             END;
  509.           END;
  510.         END; (* IF NoErr *)
  511.         Exit := TRUE;
  512.  
  513.   (*------  Ignore unknown data:  ------*)
  514.  
  515.       ELSE
  516.         len := Read(InH,Buffer,4);
  517.         i := LONGBuffer^[0];
  518.         WHILE i>256 DO
  519.           len := Read(InH,Buffer,256);
  520.           DEC(i,256);
  521.         END;
  522.         len := Read(InH,Buffer,i);
  523.       END;
  524.  
  525.     END;   (* WHILE NOT(Exit DO *)
  526.   END;   (* IF NoErr *)
  527.  
  528.   IF InH#NIL THEN Close(InH); InH := NIL; END;
  529.   IF NOT(NoErr) THEN
  530.     IF Window#NIL THEN CloseWindow(Window) END;
  531.     IF Screen#NIL THEN CloseScreen(Screen) END;
  532.   END;
  533.   OnDisplay();
  534.   RETURN NoErr;
  535. END ReadILBM; (* that's it *)
  536.  
  537. (*---------------  Procedures for ColorCycling:  --------------------------*)
  538.  
  539. PROCEDURE CycleInterrupt();
  540.  
  541. BEGIN
  542.   INLINE(MOVEMS,3F3EH);
  543.  
  544.   IntInfo := ADDRESS(REG(9));
  545.   IF CRNG IN IntInfo^.IFFTitle THEN
  546.     IntNum := IntInfo^.Internal.CycleID;
  547.     WITH CycleInfos[IntNum] DO
  548.       IntCount := 0;
  549.       WHILE IntCount<IntInfo^.CRNG.count DO
  550.         WITH IntInfo^.CRNG.data[IntCount] DO
  551.           IF on THEN
  552.             INC(speedCnt[IntCount],rate);
  553.             IF speedCnt[IntCount]>=4000H THEN
  554.               (* this 4000H should have been 8000H, but then it's to slow. *)
  555.               (* dont know why, but this way, it works correctly           *)
  556.               DEC(speedCnt[IntCount],4000H);
  557.               IF forward THEN
  558.                 IF count[IntCount]<=low THEN
  559.                   count[IntCount]:=high;
  560.                 ELSE
  561.                   DEC(count[IntCount]);
  562.                 END;
  563.               ELSE
  564.                 IF count[IntCount]>=high THEN
  565.                   count[IntCount]:=low;
  566.                 ELSE
  567.                   INC(count[IntCount]);
  568.                 END;
  569.               END;
  570.               IntCount3 := count[IntCount];
  571.               IntCount2 := low;
  572.               WHILE IntCount2<=high DO
  573.                 SetRGB4(VP,IntCount2,IntInfo^.CMAP.red[IntCount3],
  574.                                      IntInfo^.CMAP.green[IntCount3],
  575.                                      IntInfo^.CMAP.blue[IntCount3]);
  576.                 INC(IntCount3);
  577.                 IF IntCount3>high THEN IntCount3:=low END;
  578.                 INC(IntCount2);
  579.               END;
  580.             END;
  581.           END;
  582.         END;
  583.         INC(IntCount);
  584.       END;
  585.     END;
  586.   END;
  587.  
  588.   INLINE(MOVEML,7CFCH);
  589. END CycleInterrupt;
  590.  
  591. PROCEDURE DoCycle(Info: IFFInfoTypePtr; Screen: ScreenPtr): BOOLEAN;
  592. (* this creates an interrupt, that does cycling. You needn't worry,        *)
  593. (* whether there's cycling data or not. Don't forget to call EndCycle to   *)
  594. (* remove the Cycling-Interrupt !!!                                        *)
  595. (* If result is false, any error occured. Don't call EndCycle in this case!*)
  596.  
  597. BEGIN
  598.   i:=0;
  599.   LOOP
  600.     IF CycleInfos[i].VP=NIL THEN EXIT END;
  601.     INC(i);
  602.     IF i=32 THEN RETURN FALSE END;
  603.   END;
  604.   Info^.Internal.CycleID := i;
  605.   WITH CycleInfos[i] DO
  606.     VP := ADR(Screen^.viewPort);
  607.     IF CRNG IN Info^.IFFTitle THEN
  608.       FOR j:=0 TO Info^.CRNG.count-1 DO
  609.         count[j] := Info^.CRNG.data[j].low;
  610.         speedCnt[j] := 0;
  611.       END;
  612.     END;
  613.     WITH int DO
  614.       node.type := interrupt;
  615.       node.pri  := -60;
  616.       node.name := NIL;
  617.       data := Info;
  618.       code := ADR(CycleInterrupt);
  619.     END;
  620.     AddIntServer(vertb,ADR(int));
  621.   END;
  622.   RETURN TRUE;
  623. END DoCycle;
  624.  
  625. PROCEDURE EndCycle(Info: IFFInfoTypePtr);
  626. (* remove cycling-Interrupt                                                *)
  627.  
  628. BEGIN
  629.   i := Info^.Internal.CycleID;
  630.   RemIntServer(vertb,ADR(CycleInfos[i].int));
  631.   CycleInfos[i].VP := NIL;
  632. END EndCycle;
  633.  
  634. (*------------------------  TermProcedure:  -------------------------------*)
  635.  
  636. PROCEDURE CleanUp();
  637.  
  638. BEGIN
  639.   IF InH#NIL THEN Close(InH) END;
  640.   FreeMem(Buffer,768);
  641. END CleanUp;
  642.  
  643. (*-----------------------  Initialization:  -------------------------------*)
  644.  
  645. BEGIN
  646.   Buffer := AllocMem(768,MemReqSet{chip,memClear});
  647.   Assert(Buffer#NIL,ADR("Not enough ChipMem !!!"));
  648.   TextBuffer := Buffer;
  649.   LONGBuffer := Buffer;
  650.   WORDBuffer := Buffer;
  651.   BYTEBuffer := Buffer;
  652.   RQBuffer := ADDRESS(Buffer+256);
  653.   InH := NIL;
  654.   FOR i:=0 TO 31 DO CycleInfos[i].VP:=NIL END;
  655.   TermProcedure(CleanUp);
  656. END IFFLoad.
  657.